using System;
using System.Globalization;


namespace Waymex.Gps.Nmea
{
	/// <summary>
	/// RMB NMEA sentence class.
	/// </summary>
	sealed public class SentenceRmb : Sentence
	{
		private const string C_SENTENCE_TYPE = "RMB";

		/// <summary>
		/// Enumeration describing the RMB direction.
		/// </summary>
		public enum RmbDirection
		{
			/// <summary>
			/// Unknown.
			/// </summary>
			Unknown = 0,
			/// <summary>
			/// Left.
			/// </summary>
			Left = 1,
			/// <summary>
			/// Right.
			/// </summary>
			Right = 2,
		}
		private double m_dblCrossTrackError = 0.0;
		private bool m_blnReceiverWarning = false;
		private RmbDirection m_utDirectionToSteer = RmbDirection.Unknown;
		private string m_strToWaypoint = "";
		private string m_strFromWaypoint = "";
		private double m_dblDestinationLatitude = 0.0;
		private double m_dblDestinationLongitude = 0.0;
		private double m_dblRangeToDestination = 0.0;
		private double m_dblBearingToDestination = 0.0;
		private double m_dblDestinationClosingVelocity = 0.0;
		private bool m_blnArivalCircleEntered = false;


        /// <summary>
        /// Constructor for the class.
        /// </summary>
        /// <param name="sentence">NMEA sentence.</param>
        public SentenceRmb(string sentence)
            : base(sentence)
		{
			try
			{

				//check the type to ensure that we can continue
				if(this.TypeId.ToUpper(CultureInfo.InvariantCulture) == C_SENTENCE_TYPE)
				{
					Populate(sentence);
				}
				else
				{
					throw new InvalidSentence(C_MSG_001);
				}
			}
			catch(Exception e)
			{
                throw new InvalidSentence(e.Message, e);
			}
		}

		private void Populate(string p_strSentence)
		{

			//element [0] already done in the base class
			try
			{
				if(SentenceItemExists(1))
				{
					if(m_astrSentence[1].ToUpper(CultureInfo.InvariantCulture) == "A") //A = OK, V = Invalid
					{
						m_blnReceiverWarning = false;
					}
					else
					{
						m_blnReceiverWarning = true;
					}
				}
				else
				{
					m_blnReceiverWarning = false;
				}

				if(SentenceItemExists(2)) m_dblCrossTrackError = FormatNumber(m_astrSentence[2]);
				if(SentenceItemExists(3)) 
				{
					switch(m_astrSentence[3].ToUpper(CultureInfo.InvariantCulture))
					{
						case "LEFT":
							m_utDirectionToSteer = RmbDirection.Left;
							break;
						case "RIGHT":
							m_utDirectionToSteer = RmbDirection.Right;
							break;
						default:
							m_utDirectionToSteer = RmbDirection.Unknown;
							break;
					}
				}
				else
				{
					m_utDirectionToSteer = RmbDirection.Unknown;
				}
				if(SentenceItemExists(4)) m_strToWaypoint = m_astrSentence[4];
				if(SentenceItemExists(5)) m_strFromWaypoint = m_astrSentence[5];
				if(SentenceItemExists(7)) m_dblDestinationLatitude = FormatPosition(m_astrSentence[6] + m_astrSentence[7]);
				if(SentenceItemExists(9)) m_dblDestinationLongitude = FormatPosition(m_astrSentence[8] + m_astrSentence[9]);
				if(SentenceItemExists(10)) m_dblRangeToDestination = FormatNumber(m_astrSentence[10]);
				if(SentenceItemExists(11)) m_dblBearingToDestination = FormatNumber(m_astrSentence[11]);
				if(SentenceItemExists(12)) m_dblDestinationClosingVelocity = FormatNumber(m_astrSentence[12]);
           
				if(SentenceItemExists(13))
				{
					if(m_astrSentence[12].ToUpper(CultureInfo.InvariantCulture) == "A")
					{
						m_blnArivalCircleEntered = true;
					}
					else
					{
						m_blnArivalCircleEntered = false;
					}
				}
				else
				{
					m_blnArivalCircleEntered = false;
				}
			}
			catch(Exception e)
			{
                throw new InvalidSentence(e.Message, e);
			}
		}

		///<summary>
		///Returns the Cross Track Error in Nautical Miles.
		///</summary>
		public double CrossTrackError
		{
			get
			{
				return m_dblCrossTrackError;
			}
		}

		
		///<summary>
		///Returns the Direction to Steer.
		///</summary>
		public RmbDirection DirectionToSteer
		{
			get
			{
				return m_utDirectionToSteer;
			}
		}
		///<summary>
		///Returns the Navigation Receiver Warning.
		///</summary>
		public bool ReceiverWarning
		{
			get
			{
				return m_blnReceiverWarning;
			}
		}
		///<summary>
		///Returns the name of the destination Waypoint.
		///</summary>
		public string ToWaypoint
		{
			get
			{
				return m_strToWaypoint;
			}
		}
		///<summary>
		///Returns the name of the originating Waypoint.
		///</summary>
		public string FromWaypoint
		{
			get
			{
				return m_strFromWaypoint;
			}
		}
		///<summary>
		///Returns the Latitude in Degrees of destination Waypoint. Negative values indicate positions West.
		///</summary>
		public double DestinationLatitude
		{
			get
			{
				return m_dblDestinationLatitude;
			}
		}
		///<summary>
		///Returns the Longitude in Degrees of destination Waypoint. Negative values indicate positions South.
		///</summary>
		public double DestinationLongitude
		{
			get
			{
				return m_dblDestinationLongitude;
			}
		}
		///<summary>
		///Returns the range to destination in Nautical Miles.
		///</summary>
		public double RangeToDestination
		{
			get
			{
				return m_dblRangeToDestination;
			}
		}
		///<summary>
		///Returns the Bearing to destination in Degrees True.
		///</summary>
		public double BearingToDestination
		{
			get
			{
				return m_dblBearingToDestination;
			}
		}
		///<summary>
		///Returns the Destination Closing Velocity in Knots.
		///</summary>
		public double DestinationClosingVelocity
		{
			get
			{
				return m_dblDestinationClosingVelocity;
			}
		}
		///<summary>
		///Indicates whether the Arival Circle has been entered.
		///</summary>
		public bool ArrivalCircleEntered
		{
			get
			{
				return m_blnArivalCircleEntered;
			}
		}
	}
}
